﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using DEFLib;
using System.ComponentModel;
using System.IO;

namespace DeleteEmptyFolders
{
	/// <summary>
	/// Interaction logic for MainWindow.xaml
	/// </summary>
	public partial class MainWindow : Window
	{
		private FolderDeleterSettings settings = null;

		public MainWindow()
		{
			InitializeComponent();
		}

		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			reloadSettings();
			refreshIgnoreFiles();
			refreshBaseDirs();
		}

		private void refreshBaseDirs()
		{
			BaseDirsLB.Items.Clear();
			foreach (string baseDir in settings.BaseDirs)
			{
				BaseDirsLB.Items.Add(baseDir);
			}
		}

		private void reloadSettings()
		{
			settings = FolderDeleterSettings.LoadFromDisk();
		}

		private void refreshIgnoreFiles()
		{
			IgnoreFilesLB.Items.Clear();
			foreach (string ignore in settings.IgnoreFiles)
			{
				IgnoreFilesLB.Items.Add(ignore);
			}
		}

		private void RemoveIgnoreButton_Click(object sender, RoutedEventArgs e)
		{
			string selected = IgnoreFilesLB.SelectedItem.ToString();
			settings.IgnoreFiles = settings.IgnoreFiles.Where(i => i != selected).ToArray();
			settings.Save();
			reloadSettings();
			refreshIgnoreFiles();
		}

		private void RemoveIgnoreDirButton_Click(object sender, RoutedEventArgs e)
		{
			string selected = IgnoreDirsLB.SelectedItem.ToString();
			settings.IgnoreDirs = settings.IgnoreDirs.Where(i => i != selected).ToArray();
			settings.Save();
			reloadSettings();
			refreshIgnoreDirs();
		}

		private void AddIgnoreButton_Click(object sender, RoutedEventArgs e)
		{
			HashSet<string> ignores = new HashSet<string>(settings.IgnoreFiles);
			ignores.Add(AddNewIgnoreTB.Text);
			settings.IgnoreFiles = ignores.ToArray();
			settings.Save();
			reloadSettings();
			refreshIgnoreFiles();
		}

		private void AddIgnoreDirButton_Click(object sender, RoutedEventArgs e)
		{
			HashSet<string> ignores = new HashSet<string>(settings.IgnoreDirs);
			ignores.Add(AddNewIgnoreDirTB.Text);
			settings.IgnoreDirs = ignores.ToArray();
			settings.Save();
			reloadSettings();
			refreshIgnoreDirs();
		}

		private void refreshIgnoreDirs()
		{
			IgnoreDirsLB.Items.Clear();
			foreach (string ignore in settings.IgnoreDirs)
			{
				IgnoreDirsLB.Items.Add(ignore);
			}
		}

		private void RemoveBaseDirButton_Click(object sender, RoutedEventArgs e)
		{
			string selected = BaseDirsLB.SelectedItem.ToString();
			settings.BaseDirs = settings.BaseDirs.Where(i => i != selected).ToArray();
			settings.Save();
			reloadSettings();
			refreshBaseDirs();
		}

		private void AddBaseDirButton_Click(object sender, RoutedEventArgs e)
		{
			HashSet<string> baseDirs = new HashSet<string>(settings.BaseDirs);
			baseDirs.Add(AddNewBaseDirTB.Text);
			settings.BaseDirs = baseDirs.ToArray();
			settings.Save();
			reloadSettings();
			refreshBaseDirs();
		}

		private void FindBTN_Click(object sender, RoutedEventArgs e)
		{
			setDeleterFormEnabled(false);
			runBackground(new Action(() =>
				{

					if (settings == null)
					{
						reloadSettings();
					}

					executeOnUIThread(
					  new Action(() =>
						{
							FoundFoldersLB.Items.Clear();
							OutputTB.Clear();
						})
					);

					logMessage("Beginning find operation...");

					foreach (string baseDir in settings.BaseDirs)
					{
						logMessage("Searching Base Directory: '{0}'...", baseDir);
						IEnumerable<string> dirsToDelete = FolderDeleter.GetDirsToDelete(settings.IgnoreFiles, settings.IgnoreDirs, baseDir);
						foreach (string dirToDelete in dirsToDelete.OrderBy(d => d))
						{
							logMessage("Found folder: '{0}'", dirToDelete);
							executeOnUIThread(
							  new Action(() =>
								{
									FoundFoldersLB.Items.Add(dirToDelete);
								})
							);
						}
						logMessage("Finished searching '{0}'", baseDir);
					}

					logMessage("Find complete.");
				}),
				new Action(() =>
				{
					//FindBTN.IsEnabled = true;
					setDeleterFormEnabled(true);
					SelectAllBTN_Click(this, new RoutedEventArgs());
					FoundFoldersLB.Focus();
				})
			);
		}

		private void runBackground(Action action, Action actionCompletedAction)
		{
			BackgroundWorker worker = new BackgroundWorker();
			//Gets or sets a value indicating whether the BackgroundWorker can report progress updates.
			worker.WorkerReportsProgress = false;
			//Gets or sets a value indicating whether the BackgroundWorker supports asynchronous cancellation.
			worker.WorkerSupportsCancellation = true;
			//Starts execution of a background operation.
			worker.RunWorkerAsync();
			//btnCancel.IsEnabled = true;
			worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
			{
				actionCompletedAction();
			};
			worker.DoWork += delegate(object s, DoWorkEventArgs args)
			{
				BackgroundWorker lWorker = s as BackgroundWorker;
				if (lWorker.CancellationPending)
				{
					args.Cancel = true;
					return;
				}
				action();
			};
		}

		private void logMessage(string msg, params object[] args)
		{
			executeOnUIThread(new Action(() => OutputTB.Text += string.Format(msg + System.Environment.NewLine, args)));
		}

		private void setDeleterFormEnabled(bool isEnabled)
		{
			executeOnUIThread(new Action(() =>
				{
					SelectAllBTN.IsEnabled = SelectNoneBTN.IsEnabled = FindBTN.IsEnabled = DeleteBTN.IsEnabled = FoundFoldersLB.IsEnabled = isEnabled;
				}));
		}

		private void setExplorerFormEnabled(bool isEnabled)
		{
			executeOnUIThread(new Action(() =>
				{
					FolderPathTB.IsEnabled = ShowFolderBTN.IsEnabled = FilesLB.IsEnabled = isEnabled;
				}));
		}
		private void executeOnUIThread(Action action)
		{
			Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, action);
		}

		private void SelectAllBTN_Click(object sender, RoutedEventArgs e)
		{
			FoundFoldersLB.SelectAll();
		}

		private void SelectNoneBTN_Click(object sender, RoutedEventArgs e)
		{
			FoundFoldersLB.UnselectAll();
		}

		private void DeleteBTN_Click(object sender, RoutedEventArgs e)
		{
			List<string> foundDirs = new List<string>();
			foreach (var item in FoundFoldersLB.SelectedItems)
			{
				foundDirs.Add(item.ToString());
			}

			runBackground(new Action(() =>
					{
						executeOnUIThread(() =>
							{
								DeleteBTN.IsEnabled = false;
							});
						foreach (var item in foundDirs)
						{
							logMessage("Attempting to delete '{0}'...", item);
							try
							{
								FolderDeleter.RecursiveDeleteFilesAndDirectories(item);
								logMessage("'{0}' successfully deleted", item);
							}
							catch (Exception ex)
							{
								logMessage("Error attempting to delete '{0}'{1}{2}", item, System.Environment.NewLine, ex);
							}
						}
					}),
					new Action(() => DeleteBTN.IsEnabled = true)
			);
		}

		private void ShowFolderBTN_Click(object sender, RoutedEventArgs e)
		{
			string path = FolderPathTB.Text;
			setExplorerFormEnabled(false);
			runBackground(new Action(() =>
			{

				if (settings == null)
				{
					reloadSettings();
				}

				executeOnUIThread(
				  new Action(() =>
				  {
					  FilesLB.Items.Clear();
				  })
				);

				IEnumerable<string> dispositions = FolderDeleter.GetFolderFileDisposition(settings.IgnoreFiles, path);
				foreach (string file in dispositions)
				{
					executeOnUIThread(
					  new Action(() =>
					  {
						  FilesLB.Items.Add(file);
					  })
					);
				}
			}),
				new Action(() =>
				{
					//FindBTN.IsEnabled = true;
					setExplorerFormEnabled(true);
					FilesLB.Focus();
				})
			);
		}




	}
}
